﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SafeScript.MetaModel.Statements;
using PerCederberg.Grammatica.Runtime;

namespace SafeScript.MetaModel
{
    public class Property : MemberVariable, IMember
    {
        public PropertyGetter Getter;
        public PropertySetter Setter;

        public override MemberVariable Instantiate(Dictionary<TemplateParameterType, ITypeDef> templateArguments)
        {
            Property v = new Property() { Name = this.Name, IsStatic = this.IsStatic, Template = this, Attributes = this.Attributes };
            v.Type = this.Type.Instantiate(templateArguments);
            if (this.Getter != null)
                v.Getter = this.Getter.Instantiate(v);
            if (this.Setter != null)
                v.Setter = this.Setter.Instantiate(v);
            return v;
        }
    }

    public class PropertyGetter : INamed
    {
        public string Name { get; set; }
        /// <summary>
        /// A null value indicates that the compiler should implement a default getter
        /// or that the property is abstract.
        /// </summary>
        public Node StatementsNode;
        public StatementList Statements;
        public bool IsOverride;
        public bool IsAbstract;
        public bool IsSealed;
        public Property Property;
        public Namespace Owner;
        /// <summary>
        /// May be null.
        /// </summary>
        public PropertyGetter OverridenGetter;

        internal PropertyGetter Instantiate(Property prop)
        {
            return new PropertyGetter() { Name = this.Name, IsOverride = this.IsOverride, IsAbstract = this.IsAbstract, IsSealed = this.IsSealed, Property = prop, Owner = this.Owner };
        }
    }

    public class PropertySetter : INamed
    {
        public string Name { get; set; }
        /// <summary>
        /// A null value indicates that the compiler should implement a default getter
        /// or that the property is abstract.
        /// </summary>
        public Node StatementsNode;
        public StatementList Statements;
        public bool IsOverride;
        public bool IsAbstract;
        public bool IsSealed;
        public Property Property;
        public Namespace Owner;
        /// <summary>
        /// May be null.
        /// </summary>
        public PropertySetter OverridenSetter;

        internal PropertySetter Instantiate(Property prop)
        {
            return new PropertySetter() { Name = this.Name, IsOverride = this.IsOverride, IsAbstract = this.IsAbstract, IsSealed = this.IsSealed, Property = prop, Owner = this.Owner };
        }
    }
}
